// Copyright (C) 2012 Volkov Zachar
// This file is part of the "zAxis Game Engine".
// For conditions of distribution and use, see copyright notice zx_Common.hpp

#include "zx_FileSystem.hpp"

namespace zx {

//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
MemoryStream::MemoryStream( DataStreamPtr _src, uint _flags, const String& _name ) : m_data( 0 ), m_flags( _flags ), m_pos( 0 )
{
     m_name = _name;
     m_access = m_flags & AM_READ_WRITE;

     if( _src )
     {
          m_size = _src -> GetSize();

          if( m_name.empty() )
          {
               m_name = _src -> GetName();
          }

          if( m_size )
          {
               m_data = new uint8[ m_size ];

               uint _old_pos = _src -> GetPos();
               _src -> SetPos( 0 );
               m_size = _src -> Read( m_data, m_size );
               _src -> SetPos( _old_pos );
          }
     }
}
//----------------------------------------------------------------------------//
MemoryStream::MemoryStream( void* _src, uint _size, uint _flags, const String& _name ) : m_data( 0 ), m_flags( _flags ), m_pos( 0 )
{
     m_name = _name;
     m_access = m_flags & AM_READ_WRITE;
     m_size = _size;

     if( m_size )
     {
          if( m_flags & MSF_ALLOC )
          {
               m_data = new uint8[ m_size ];
          }

          if( _src )
          {
               if( m_flags & MSF_COPY )
               {
                    memcpy( m_data, _src, m_size );
               }
               else
               {
                    m_data = (uint8*)_src;
               }
          }
     }
}
//----------------------------------------------------------------------------//
MemoryStream::~MemoryStream( void )
{
     if( m_data && ( m_flags & MSF_DELETE ) )
     {
          delete [] m_data;
     }
}
//----------------------------------------------------------------------------//
void MemoryStream::SetPos( int _pos, bool _relative )
{ 
     if( _relative )
     {
          int64 _new_pos = m_pos + _pos;
          m_pos = (uint)zxChoose( _new_pos < 0, 0, zxChoose( _new_pos > (uint)-1, (uint)-1, _new_pos ) );
     }
     else
     {
          m_pos = (uint)zxChoose( _pos < 0, 0, _pos );
     }
}
//----------------------------------------------------------------------------//
uint MemoryStream::Read( void* _dst, uint _size )
{
     if( m_data && _dst && IsReadable() )
     {
          if( m_pos < m_size )
          {
               uint _readed = Min( m_size - m_pos, _size );

               if( _readed )
               {
                    memcpy( _dst, m_data + m_pos, _readed );
               }

               m_pos += _readed;

               return _readed;
          }
     }

     return 0;
}
//----------------------------------------------------------------------------//
uint MemoryStream::Write( const void* _src, uint _size )
{
     if( m_data && _src && IsWritable() )
     {
          if( m_pos < m_size )
          {
               uint _written = Min( m_size - m_pos, _size );

               if( _written )
               {
                    memcpy( m_data + m_pos, _src, _written );
               }

               m_pos += _written;

               return _written;
          }
     }

     return 0;
}
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//

} // namespace zx
